using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Settings;
using Volo.Abp.Guids;
using Microsoft.Extensions.Logging;
using System.Text.Json;

namespace CKY.AgentPlatform.Domain.McpTools
{
    /// <summary>
    /// MCP客户端管理服务 - 管理多个MCP服务器连接
    /// </summary>
    public partial class McpClientManager : ITransientDependency
    {
        private readonly IRepository<McpTool, Guid> _mcpToolRepository;
        private readonly ISettingProvider _settingProvider;
        private readonly ILogger<McpClientManager> _logger;
        private readonly IGuidGenerator _guidGenerator;
        private readonly Dictionary<string, McpClient> _clients = new Dictionary<string, McpClient>();
        private readonly Dictionary<string, McpClientConfig> _clientConfigs = new Dictionary<string, McpClientConfig>();

        public McpClientManager(
            IRepository<McpTool, Guid> mcpToolRepository,
            ISettingProvider settingProvider,
            ILogger<McpClientManager> logger,
            IGuidGenerator guidGenerator)
        {
            _mcpToolRepository = mcpToolRepository;
            _settingProvider = settingProvider;
            _logger = logger;
            _guidGenerator = guidGenerator;
        }

        /// <summary>
        /// 初始化MCP客户端管理器
        /// </summary>
        public async Task InitializeAsync()
        {
            try
            {
                await LoadConfigurationsAsync();
                await StartAllClientsAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to initialize MCP client manager");
            }
        }

        /// <summary>
        /// 获取所有可用的MCP工具
        /// </summary>
        /// <returns>工具列表</returns>
        public async Task<List<McpToolDefinition>> GetAllAvailableToolsAsync()
        {
            var allTools = new List<McpToolDefinition>();

            foreach (var client in _clients.Values.Where(c => c.IsConnected()))
            {
                try
                {
                    var tools = client.GetAvailableTools();
                    allTools.AddRange(tools);
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "Failed to get tools from MCP client");
                }
            }

            return allTools;
        }

        /// <summary>
        /// 获取所有可用的MCP资源
        /// </summary>
        /// <returns>资源列表</returns>
        public async Task<List<McpResourceDefinition>> GetAllAvailableResourcesAsync()
        {
            var allResources = new List<McpResourceDefinition>();

            foreach (var client in _clients.Values.Where(c => c.IsConnected()))
            {
                try
                {
                    var resources = client.GetAvailableResources();
                    allResources.AddRange(resources);
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "Failed to get resources from MCP client");
                }
            }

            return allResources;
        }

        /// <summary>
        /// 调用指定工具
        /// </summary>
        /// <param name="toolName">工具名称</param>
        /// <param name="parameters">工具参数</param>
        /// <returns>执行结果</returns>
        public async Task<object> CallToolAsync(string toolName, object parameters = null)
        {
            // 查找支持该工具的客户端
            foreach (var client in _clients.Values.Where(c => c.IsConnected()))
            {
                try
                {
                    var tools = client.GetAvailableTools();
                    if (tools.Any(t => t.Name == toolName))
                    {
                        return await client.CallToolAsync(toolName, parameters);
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "Failed to call tool {ToolName} on client", toolName);
                    continue;
                }
            }

            throw new McpToolException($"Tool '{toolName}' not found in any connected MCP server");
        }

        /// <summary>
        /// 读取指定资源
        /// </summary>
        /// <param name="resourceUri">资源URI</param>
        /// <returns>资源内容</returns>
        public async Task<object> ReadResourceAsync(string resourceUri)
        {
            // 查找支持该资源的客户端
            foreach (var client in _clients.Values.Where(c => c.IsConnected()))
            {
                try
                {
                    var resources = client.GetAvailableResources();
                    if (resources.Any(r => r.Uri == resourceUri))
                    {
                        return await client.ReadResourceAsync(resourceUri);
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "Failed to read resource {ResourceUri} on client", resourceUri);
                    continue;
                }
            }

            throw new McpResourceException($"Resource '{resourceUri}' not found in any connected MCP server");
        }

        /// <summary>
        /// 添加新的MCP服务器配置
        /// </summary>
        /// <param name="config">客户端配置</param>
        public async Task AddClientAsync(McpClientConfig config)
        {
            var clientId = GenerateClientId(config.ServerUrl);
            
            if (_clients.ContainsKey(clientId))
            {
                // 先断开现有连接
                var existingClient = _clients[clientId];
                await existingClient.DisconnectAsync();
                _clients.Remove(clientId);
            }

            _clientConfigs[clientId] = config;

            var client = new McpClient(config);
            
            // 注册事件处理器
            client.OnConnectionStateChanged += (sender, isConnected) =>
            {
                _logger.LogInformation("MCP client {ClientId} connection state changed: {IsConnected}", clientId, isConnected);
            };

            client.OnToolsUpdated += (sender, tools) =>
            {
                _logger.LogInformation("MCP client {ClientId} tools updated: {ToolCount}", clientId, tools.Count);
                _ = Task.Run(() => SyncToolsToDatabaseAsync(clientId, tools));
            };

            client.OnResourcesUpdated += (sender, resources) =>
            {
                _logger.LogInformation("MCP client {ClientId} resources updated: {ResourceCount}", clientId, resources.Count);
            };

            client.OnError += (sender, ex) =>
            {
                _logger.LogError(ex, "MCP client {ClientId} error", clientId);
            };

            _clients[clientId] = client;

            // 尝试连接
            try
            {
                await client.ConnectAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to connect MCP client {ClientId}", clientId);
            }
        }

        /// <summary>
        /// 移除MCP服务器配置
        /// </summary>
        /// <param name="clientId">客户端ID</param>
        public async Task RemoveClientAsync(string clientId)
        {
            if (_clients.TryGetValue(clientId, out var client))
            {
                await client.DisconnectAsync();
                _clients.Remove(clientId);
            }

            _clientConfigs.Remove(clientId);
        }

        /// <summary>
        /// 重启指定客户端
        /// </summary>
        /// <param name="clientId">客户端ID</param>
        public async Task RestartClientAsync(string clientId)
        {
            if (_clientConfigs.TryGetValue(clientId, out var config))
            {
                await RemoveClientAsync(clientId);
                await AddClientAsync(config);
            }
        }

        /// <summary>
        /// 获取所有客户端状态
        /// </summary>
        /// <returns>客户端状态列表</returns>
        public List<McpClientStatus> GetClientStatuses()
        {
            return _clients.Select(kvp => new McpClientStatus
            {
                ClientId = kvp.Key,
                ServerUrl = _clientConfigs[kvp.Key]?.ServerUrl,
                IsConnected = kvp.Value.IsConnected(),
                ToolCount = kvp.Value.GetAvailableTools().Count,
                ResourceCount = kvp.Value.GetAvailableResources().Count
            }).ToList();
        }

        /// <summary>
        /// 获取MCP客户端
        /// </summary>
        /// <param name="clientId">客户端ID</param>
        /// <returns>MCP客户端</returns>
        public Task<McpClient> GetClientAsync(string clientId)
        {
            if (_clients.TryGetValue(clientId, out var client))
            {
                return Task.FromResult(client);
            }
            throw new KeyNotFoundException($"MCP client with ID '{clientId}' not found.");
        }

        /// <summary>
        /// 同步工具到数据库
        /// </summary>
        /// <param name="clientId">客户端ID</param>
        /// <param name="tools">工具列表</param>
        private async Task SyncToolsToDatabaseAsync(string clientId, List<McpToolDefinition> tools)
        {
            try
            {
                foreach (var tool in tools)
                {
                    // 查找数据库中是否已存在该工具
                    var existingTool = await _mcpToolRepository.FirstOrDefaultAsync(t => 
                        t.Name == tool.Name && t.Tags.Contains(clientId));

                    if (existingTool == null)
                    {
                        // 创建新工具记录
                        var mcpTool = new McpTools.McpTool(
                            _guidGenerator.Create(),
                            tool.Name,
                            tool.Description,
                            McpTools.McpToolType.Custom,
                            JsonSerializer.Serialize(tool.Configuration))
                        {
                            Configuration = JsonSerializer.Serialize(tool.InputSchema),
                            Parameters = JsonSerializer.Serialize(tool.InputSchema),
                            IsActive = true,
                            Tags = $"mcp,{clientId}",
                            Author = "MCP Server",
                            DocumentationUrl = "",
                            TimeoutSeconds = 30,
                            MaxRetries = 3
                        };

                        await _mcpToolRepository.InsertAsync(mcpTool);
                        _logger.LogInformation("Added new MCP tool: {ToolName} from client {ClientId}", tool.Name, clientId);
                    }
                    else
                    {
                        // 更新现有工具
                        existingTool.Description = tool.Description;
                        existingTool.Configuration = JsonSerializer.Serialize(tool.Configuration);
                        existingTool.Parameters = JsonSerializer.Serialize(tool.InputSchema);
                        existingTool.IsActive = true;

                        await _mcpToolRepository.UpdateAsync(existingTool);
                        _logger.LogInformation("Updated MCP tool: {ToolName} from client {ClientId}", tool.Name, clientId);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to sync tools to database for client {ClientId}", clientId);
            }
        }

        /// <summary>
        /// 加载配置
        /// </summary>
        private async Task LoadConfigurationsAsync()
        {
            try
            {
                // 从数据库加载MCP工具配置
                var mcpTools = await _mcpToolRepository.GetListAsync();
                
                foreach (var tool in mcpTools.Where(t => t.Tags.Contains("mcp")))
                {
                    try
                    {
                        // 从工具配置中解析服务器URL
                        var config = JsonSerializer.Deserialize<McpClientConfig>(tool.Configuration);
                        if (config != null)
                        {
                            var clientId = GenerateClientId(config.ServerUrl);
                            _clientConfigs[clientId] = config;
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "Failed to parse MCP tool configuration: {ToolName}", tool.Name);
                    }
                }

                // TODO: 从配置文件或数据库加载其他MCP服务器配置
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to load MCP client configurations");
            }
        }

        /// <summary>
        /// 启动所有客户端
        /// </summary>
        private async Task StartAllClientsAsync()
        {
            foreach (var config in _clientConfigs.Values)
            {
                try
                {
                    await AddClientAsync(config);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Failed to start MCP client for server: {ServerUrl}", config.ServerUrl);
                }
            }
        }

        /// <summary>
        /// 生成客户端ID
        /// </summary>
        /// <param name="serverUrl">服务器URL</param>
        /// <returns>客户端ID</returns>
        private string GenerateClientId(string serverUrl)
        {
            using var md5 = System.Security.Cryptography.MD5.Create();
            var hash = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(serverUrl));
            return BitConverter.ToString(hash).Replace("-", "").Substring(0, 8).ToLower();
        }

        /// <summary>
        /// 停止所有客户端
        /// </summary>
        public async Task ShutdownAsync()
        {
            foreach (var client in _clients.Values)
            {
                try
                {
                    await client.DisconnectAsync();
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Failed to disconnect MCP client");
                }
            }

            _clients.Clear();
            _clientConfigs.Clear();
        }
    }

    /// <summary>
    /// MCP客户端状态信息
    /// </summary>
    public class McpClientStatus
    {
        /// <summary>
        /// 客户端ID
        /// </summary>
        public string ClientId { get; set; }

        /// <summary>
        /// 服务器URL
        /// </summary>
        public string ServerUrl { get; set; }

        /// <summary>
        /// 是否已连接
        /// </summary>
        public bool IsConnected { get; set; }

        /// <summary>
        /// 工具数量
        /// </summary>
        public int ToolCount { get; set; }

        /// <summary>
        /// 资源数量
        /// </summary>
        public int ResourceCount { get; set; }
    }
}